import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;


public class BTReader {
	public static boolean LOOKUP_NOT_FOUND_EXCEPTION = true;
	
	//=== TASKS =======================================================
	//=== --- CONDITIONS ----------------------------------------------
		class CheckGripper extends BT.Task{
			public BT.STATUS step(){ return BT.STATUS.Progress; }
		}
		
		class BumpDetection extends BT.Task{
			public BT.STATUS step(){ return BT.STATUS.Progress; }
		}
		
	//=== --- GOAL SELECTION ------------------------------------------
		
		class SearchObstacle extends BT.Task{
			public BT.STATUS step(){ return BT.STATUS.Progress; }
		}
		
		class SetForwardGoal extends BT.Task{
			public BT.STATUS step(){ return BT.STATUS.Progress; }
		}

		class SetWanderingGoal extends BT.Task{
			public BT.STATUS step(){ return BT.STATUS.Progress; }
		}
		
	//=== --- MOTION --------------------------------------------------
		
		class MoveToGoal extends BT.Task{
			public BT.STATUS step(){ return BT.STATUS.Progress; }
		}

		class Wander extends BT.Task{
			public BT.STATUS step(){ return BT.STATUS.Progress; }
		}

		class Mission extends BT.Task{
			public BT.STATUS step(){ return BT.STATUS.Progress; }
		}
		
		class Stop extends BT.Task{
			public BT.STATUS step(){ return BT.STATUS.Progress; }
		}

	//=== --- COORDINATION TRACKING -----------------------------------
		
		class StartCollision extends BT.Task{
			public BT.STATUS step(){ return BT.STATUS.Progress; }
		}

		class EndCollision extends BT.Task{
			public BT.STATUS step(){ return BT.STATUS.Progress; }
		}

		class SelectSolution extends BT.Task{
			public BT.STATUS step(){ return BT.STATUS.Progress; }
		}
		
	//=== --- COORDINATION METHODS ------------------------------------
		
		class Noise extends BT.Task{
			public BT.STATUS step(){ return BT.STATUS.Progress; }
		}
		
		class Ripel extends BT.Task{
			public BT.STATUS step(){ return BT.STATUS.Progress; }
		}
		
		class Aggression extends BT.Task{
			public BT.STATUS step(){ return BT.STATUS.Progress; }
		}
		
	public BT.LookupTable lp = new BT.LookupTable();
	{
		lp.add(new CheckGripper());
		lp.add(new BumpDetection());
		lp.add(new SearchObstacle());
		lp.add(new SetForwardGoal());
		lp.add(new SetWanderingGoal());
		lp.add(new MoveToGoal());
		lp.add(new Wander());
		lp.add(new Mission());
		lp.add(new Stop());
		lp.add(new StartCollision());
		lp.add(new EndCollision());
		lp.add(new SelectSolution());
		lp.add(new Noise());
		lp.add(new Ripel());
		lp.add(new Aggression());
	}
	
	
	private String path_to_file;
	
	public BTReader(String path_to_file){
		this.path_to_file = path_to_file;
	}
	public BT.Task loadTest1(){
		BT.Task behavior = 
		new BT.Seq("Foraging")//Foraging
		.add(new BT.WhileTrue(	new BT.Seq("Work")//Work
								.add(	new BT.Par("NormalOperation")//NormalOperation
										.add(new BumpDetection())
										.add(new Mission()) 
								)
								.add(	new BT.Seq("CollisionSolution")//CollisionSolution
										.add(	new StartCollision())
										.add(	new BT.Swi()
												.add(new SelectSolution())
												
												.add(new Noise())
												.add(new Ripel())
												.add(new Aggression())
										)
										.add(new EndCollision())
								)
		))
		.add(new Stop());
		return behavior;
	}
	public BT.Task loadTest2(){
		BT.Task behavior = 
		new BT.Seq("Foraging")//Foraging
		.add(new BT.WhileTrue(	new BT.Seq("Work")//Work
								.add(	new BT.Par("NormalOperation")//NormalOperation
										.add(new BT.Lookup(lp, "SetWanderingGoal"))
										.add(new BT.Lookup(lp, "Mission")) 
								)
								.add(	new BT.Seq("CollisionSolution")//CollisionSolution
										.add(	new BT.Lookup(lp, "StartCollision"))
										.add(	new BT.Swi()
												.add(new BT.Lookup(lp, "SelectSolution"))
												
												.add(new BT.Lookup(lp, "Noise"))
												.add(new BT.Lookup(lp, "Ripel"))
												.add(new BT.Lookup(lp, "Aggression"))
										)
										.add(new BT.Lookup(lp, "EndCollision"))
								)
		))
		.add(new BT.Lookup(lp, "Stop"));
		return behavior;
	}
	public BT.Task load(BT.LookupTable lp) throws IOException{
		BufferedReader r = new BufferedReader(new FileReader(path_to_file));
		BT.Task t= load(r, lp, null, "");
		r.close();
		return t;
	}
	private String getNameAttr(String line){
		int i = line.indexOf("name=");
		if(i<0) return "";
		i+="name=".length()+1;
		int p = line.indexOf("\"",i+1);
		return line.substring(i,p);
	}
	private void addToTask(BT.Task behavior, BT.Task t){
		if(behavior instanceof BT.Seq){ ((BT.Seq)behavior).add(t); }
		if(behavior instanceof BT.Sel){ ((BT.Sel)behavior).add(t); }
		if(behavior instanceof BT.Swi){ ((BT.Swi)behavior).add(t); }
		if(behavior instanceof BT.Par){ ((BT.Par)behavior).add(t); }
		if(behavior instanceof BT.Dec){ ((BT.Dec)behavior).set(t); }
	}
	private BT.Task load(BufferedReader r, BT.LookupTable lp, BT.Task behavior, String term) throws IOException{
		String line = r.readLine();
		while(line!=null){
			line = line.trim();
			if(line.startsWith("<")==false) continue;			
			if(line.startsWith("</") && line.equals(term)){
				break;
			}
			if(line.toLowerCase().startsWith("<tsk") || line.toLowerCase().startsWith("<task")){
				String tname = getNameAttr(line);
				if(lp.contains(tname)==false && LOOKUP_NOT_FOUND_EXCEPTION){
					throw new IOException("LookupNotFoundTask: "+tname);
				}
				if(behavior==null){
					behavior = new BT.Lookup(lp, tname);
					break;
				}else{
					BT.Task t = new BT.Lookup(lp, tname);
					addToTask(behavior, t);
				}
			}else{
				String nstop = null;
				BT.Task t = null;
				if(line.toLowerCase().startsWith("<seq ")){
					nstop = "</seq>";
					t = new BT.Seq(getNameAttr(line));
					if(behavior==null) behavior = t;
					else addToTask(behavior, t);
				}else
				if(line.toLowerCase().startsWith("<sel ")){
					nstop = "</sel>";
					t = new BT.Sel(getNameAttr(line));
					if(behavior==null) behavior = t;
					else addToTask(behavior, t);
				}else
				if(line.toLowerCase().startsWith("<swi ")){
					nstop = "</swi>";
					t = new BT.Swi(getNameAttr(line));
					if(behavior==null) behavior = t;
					else addToTask(behavior, t);
				}else
				if(line.toLowerCase().startsWith("<par ")){
					nstop = "</par>";
					t = new BT.Par(getNameAttr(line));
					if(behavior==null) behavior = t;
					else addToTask(behavior, t);
				}else
				if(line.toLowerCase().startsWith("<dec ")){
					nstop = "</dec>";
					t = BT.Dec.create(getNameAttr(line));
					if(behavior==null) behavior = t;
					else addToTask(behavior, t);
				}else
				/*if(line.toLowerCase().startsWith("<plan "))*/{
					nstop = "</"+line.substring(1, line.indexOf(" "))+">";
					t = new BT.ASIS(null);
					if(behavior==null) behavior = t;
					else addToTask(behavior, t);
				}
				load(r, lp, t, nstop);
			}
			
			line = r.readLine();
		}
		return behavior;
	}
	public static void main(String[] args) throws IOException {
		BTReader reader = new BTReader("/tmp/BT.xml");
		BT.Task bt = reader.load(reader.lp);
		System.out.println("BT: \n"+bt.toString());
	}

}
